/*
 * 工单使用配件 2020 02 11 从借出的配件 里 -->选择配件
 */
public without sharing class WorkOrderProductController
{
    public String maccuraJson {get;private set;}
    public String msg {get; private set;}
    public Boolean isErr {get; private set;}
    public Boolean isSuccess {get;private set ;}

    public String backId {get;private set;}

    public String dataJson {get;private set;}
    public String saveJson {get; set;}
    public String companyCode {get;set;}
    public Boolean isExpired {get;private set;}//服务仪器是否到期
    public  Boolean isDealer {get; private set;}//是否为经销商配件借出
    public Boolean isAssit {get; private set;}//当前操作人是否为助理
    private  Map<String,DataUtil.SObjectBean> stageObjectMap;

    private WorkOrder__c wo ;
    public WorkOrderProductController()
    {

        //获得仪器id
        backId = System.currentPageReference().getParameters().get('id');
        wo = new WorkOrder__c();
        stageObjectMap  = new  Map<String,DataUtil.SObjectBean> ();
        isAssit = false;
        maccuraJson = MaccuraBrandUtil.getMaccuraJson();

    }
    
    public void init(){
            
        try {

            String accNumber = '';

            if(Id.valueOf(backId).getSobjecttype() == WorkOrder__c.SObjecttype){
                wo = [select Case__r.Status, Id,ServiceManufacture__c,ServiceManufacture__r.EndDate__c ,Technician__r.ClientCode__c,Confirm_NC_issue__c, Technician__c,NotificationAssistant__c,InventoryOrganization__c from WorkOrder__c where Id=:backId];
                if(wo.ServiceManufacture__c == null ) throw new DmlException('工单服务仪器为空,不能添加配件!');
                isDealer = wo.Technician__r.ClientCode__c != null ;

                isExpired = wo.ServiceManufacture__r.EndDate__c == null  ||  wo.ServiceManufacture__r.EndDate__c.addYears(1).daysBetween(System.today())>0 ;
                
                if(wo.Technician__r.ClientCode__c!= null ) isExpired = false;
                accNumber = wo.Technician__r.ClientCode__c;
               isAssit = [select EngineeringAssistant__c from User where Id=:UserInfo.getUserId()].EngineeringAssistant__c;
                if(!isAssit && [select count() from  PartsInvoiceApplication__c where RelatedWorkOrder__c =:backId and Status__c = '已批准' ]>0)throw new DmlException('发票申请已通过审批,不能修改!');
                if(wo.Confirm_NC_issue__c == true ) throw new DmlException('已同步NC,不能修改!');
                if(wo.NotificationAssistant__c != null && !isAssit ) throw new DmlException('已通知助理,不能修改!');
                if(wo.Case__r.Status == '关闭' && !isAssit )throw new DmlException('个案关闭不能添加配件!');
            }else{
                throw new DmlException('页面打开错误!');
            }


            List<Account> accs = [select Id ,Name from Account where AccountNumber =:accNumber];
          if(accs.isEmpty() && isDealer ) throw new DmlException('请联系管理员维护用户信息的对应客户编码!');

            Map<String,Object> dataMap = new Map<String,Object>();
            dataMap.put('detail', getDetail());


                    //字段
             Map<String,Set<String>> fieldsmap = getFields();
             //字段详情
             Map<String, List<DataUtil.FieldBean>> fbMap = DataUtil.getFieldsBean(fieldsmap,stageObjectMap);
            
            //字段赋值
             Map<String,List<DataUtil.FieldBean>> fields = DataUtil.setFieldsValue(fbMap,DataUtil.getBaseInfo(fbMap,stageObjectMap) );
            
            
              //后续处理方式为“经销商备用”，申请库存组织默认为“四川省迈克实业有限公司”，“开票客户”、“终端客户”默认为本经销商（通过用户上的客户编码查找的客户）
              //，且只能选择品牌为迈克的配件

              for (DataUtil.FieldBean fb   :  fields.get('WorkOrder__c')) {
                Map<String,Object> vMap  = new Map<String,Object>();
                if(isDealer){
                    if(fb.name == 'PartsInvoicingCustomers__c'){

                        vMap.put('Id', accs[0].Id );
                        vMap.put('Name', accs[0].Name );
                        fb.value = vMap;
                    }
                    if(fb.name == 'InventoryOrganization__c')fb.value = 'MKSY';
                }
                

                if(fb.name == 'FollowupProcessing__c')fb.value = '其他出入库';

                 if(fb.name =='DocumentTypes__c')fb.value = '库存其他出库单';
             

            }
            dataMap.put('base',fields);

            dataMap.put('baseObject',DataUtil.getBaseObjectMap(stageObjectMap));

            dataJson= EncodingUtil.urlEncode(JSON.serialize(dataMap), 'UTF-8');


        }
        catch (Exception e) {
            isErr = true ;
            ApexPages.addMessage( new ApexPages.Message(ApexPages.Severity.ERROR ,e.getMessage()));
        }
        
    }


    public Map<String,Set<String>>  getFields(){
        Map<String,Set<String>> fieldsMap  = new  Map<String,Set<String>>();
        
            DataUtil.SObjectBean sb = new DataUtil.SObjectBean();

            sb.title ='';
            sb.objname = 'WorkOrder__c';
            sb.stype = DataUtil.getSObjectType(sb.objname);
            sb.idvalue = backId;
            sb.type = 'base';
            sb.condition = ' where Id =\''+backId +'\'';
            stageObjectMap.put(sb.objname,sb );
            //
            Set<String>  fields = new Set<String>{'DocumentTypes__c','PartsInvoicingCustomers__c','FollowupProcessing__c',
                    'ConsigneePhone__c','InstallmentSale__c','ReceivingRemarks__c','PhysicalDelivery__c','InventoryOrganization__c','Remark__c'
                };
         
            fieldsMap.put(sb.objname, fields);
        
        return fieldsMap;
    }
    public List<ProductBean> getDetail(){
        List<ProductBean> tmp = new List<ProductBean>();

        for (WorkOrderProduct__c wp  :[select Id,Product__c,Product__r.Name ,PartsLendingDetails__r.LendingMargin__c ,Product__r.Brand__c,Product__r.NCCode__c,Product__r.Category0__c,
            PartsLendingDetails__c, WarrantyNo__c,InvoiceNo__c,Quantity__c,OldPartsNumber__c,NewPartsNumber__c ,PartsLendingDetails__r.PartsLendingApplication__r.Name 
             from WorkOrderProduct__c where WorkOrder__c =:backId ] ) {
            tmp.add(new ProductBean(wp));

        }
         return tmp;
    }

    public void getSearch(){
        List<ProductBean> tmp = new List<ProductBean>();
        System.debug('WorkOrderProductController==>'+wo.Technician__c + ' 当前 '+UserInfo.getUserId() + ' '+companyCode);
        for (PartsLendingDetails__c p :[select Id ,Product__c ,PartsLendingApplication__r.Name,Product__r.Name ,LendingMargin__c,Product__r.NCCode__c,Product__r.Brand__c,Product__r.Spec__c,Product__r.Category0__c,
          Product__r.SerialNo__c from PartsLendingDetails__c 
            where PartsLendingApplication__r.OwnerId =: wo.Technician__c  and LendingMargin__c > 0 
            and PartsLendingApplication__r.IsSycToNc__c = true and PartsLendingApplication__r.InventoryOrganization__c =:companyCode  ] ) {
            
            tmp.add(new ProductBean(p));
        }
        dataJson= EncodingUtil.urlEncode(JSON.serialize(tmp), 'UTF-8');

    }
    public void setNil(){
        dataJson = '';
        saveJson = '';
    }
    public void save(){
        msg = '';
        try {

            Map<String,Object>saveMap = (Map<String,Object>) JSON.deserializeUntyped(EncodingUtil.urlDecode(saveJson, 'UTF-8'));
            Map<String,Set<String>> fieldsMap = getFields();
            Map<String,DataUtil.FieldBean> fbeanMap = DataUtil.getFieldsInfo(WorkOrder__c.SObjecttype,fieldsMap.get('WorkOrder__c'));


                Map<String,Object> obj = (Map<String,Object>) saveMap.get('base');

                for (String field :  obj.keySet()) {

                    if(obj.get(field) == null || DataUtil.getStringValue(obj.get(field)) == '') continue;

                    if(fbeanMap.containsKey(field) )wo.put(field, DataUtil.dataHandler(obj.get(field),fbeanMap.get(field).type.toUpperCase() ));

                }
            List<Object> saveList = (List<Object>) saveMap.get('datas');

            List<WorkOrderProduct__c> details =  new List<WorkOrderProduct__c>();
            Set<String> exset = new Set<String>();

            Map<String,Decimal>restMap = new Map<String,Decimal>();

            for (Object o  : saveList) {
                
                Map<String,Object> mo =(Map<String,Object>) o;
                WorkOrderProduct__c wp = new WorkOrderProduct__c();
                wp.Product__c = DataUtil.getStringValue(mo.get('productId'));
                wp.Quantity__c = DataUtil.getDecimalValue(mo.get('num'));
                wp.WorkOrder__c = wo.Id;
                wp.PartsLendingDetails__c = DataUtil.getStringValue(mo.get('lendingId'));
                wp.InvoiceNo__c = DataUtil.getDecimalValue(mo.get('invoiceNum'));
                wp.WarrantyNo__c = DataUtil.getDecimalValue(mo.get('freeNum'));
                wp.OldPartsNumber__c =  DataUtil.getStringValue(mo.get('oldpartsNum'));
                wp.NewPartsNumber__c =  DataUtil.getStringValue(mo.get('newpartsNum'));
                wp.Id = DataUtil.getStringValue(mo.get('detailId'));  
                if(wp.Id != null )exset.add(wp.Id);
                details.add(wp);

                restMap.put(wp.PartsLendingDetails__c,wp.Quantity__c == null ? 0 : wp.Quantity__c );
            }
            //保存之前验证是否超过实际借出
             //保存之前去验证是否有余量
            Map<Id,Decimal>qMap = new Map<Id,Decimal>();
            for(WorkOrderProduct__c wp:[select PartsLendingDetails__c ,Id,Quantity__c from WorkOrderProduct__c where PartsLendingDetails__c in:restMap.keySet() and Id not in: exset]){

                Decimal q = wp.Quantity__c == null ? 0 : wp.Quantity__c;
                q =  q + ( qMap.containsKey(wp.PartsLendingDetails__c) ?qMap.get(wp.PartsLendingDetails__c) : 0) ;

                qMap.put(wp.PartsLendingDetails__c,q);

            }
            List<String> cerrors = new List<String>();
            List<String> errors = new List<String>();
            for(PartsLendingDetails__c pd : [select Id,Name,LendingMargin__c,B_No__c from PartsLendingDetails__c where Id in:restMap.keySet()]){
                if(restMap.containsKey(pd.Id)){
                    
                    if((restMap.get(pd.Id) == null ? 0 :restMap.get(pd.Id))  > (pd.LendingMargin__c == null ? 0: pd.LendingMargin__c)  )errors.add(pd.Name+':'+pd.LendingMargin__c );

                    if(pd.B_No__c == null || pd.B_No__c < (restMap.get(pd.Id)+(qMap.containsKey(pd.Id) ? qMap.get(pd.Id) : 0  )  ))cerrors.add(pd.Name+':'+pd.LendingMargin__c );


                    restMap.remove(pd.Id);


                }
            }


            if(!cerrors.isEmpty() && !isAssit)msg = '下列配件申请使用超过借出数量:'+String.join(cerrors, ',');
            if(String.isNotBlank(msg) && !isAssit )return;

            if(!errors.isEmpty() && !isAssit)msg = '下列配件借出都超过配件剩余量:'+String.join(errors, ',');
            if(String.isNotBlank(msg) && !isAssit )return;
            if(!restMap.isEmpty() && !isAssit)  msg = '异常配件还回:'+JSON.serialize(restMap.keySet());
            if(String.isNotBlank(msg) && !isAssit)return;


            Savepoint sp = Database.setSavepoint();
            try {
                update wo;
               if(!isAssit && !details.isEmpty() )delete [select Id from  WorkOrderProduct__c where WorkOrder__c =:wo.Id and Id not in: exset];
               if(!isAssit && !details.isEmpty()) upsert details;

               isSuccess = true;
               msg = '保存成功!';
                
            } catch (Exception e) {
                Database.rollback(sp);
                msg = '保存失败:'+e.getMessage() +e.getStackTraceString();
            } 
            
            
            
        }catch (Exception e) {
            msg = '保存失败:'+e.getMessage()+e.getStackTraceString();

        }
        
        
   }
    
    

    public class ProductBean {
        public String productId ;
        public String detailId ;
        public String productName;
        public String lendingId;
        public String lendingName;

        public Decimal num;
        public Decimal invoiceNum;
        public Decimal freeNum;

        public Decimal maxNum ;

        public String oldpartsNum;//原配件号
        public String newpartsNum;//新配件号

        public String brand;
        public String nccode;
        public String spec;
        public String serialno;
        public String cate0;


        public ProductBean(WorkOrderProduct__c wp ) {

            productName = wp.Product__r.Name;
            productId = wp.Product__c;
            brand = wp.Product__r.Brand__c;
            cate0 = wp.Product__r.Category0__c;
            nccode = wp.Product__r.NCCode__c;
            detailId = wp.Id;
            lendingId = wp.PartsLendingDetails__c;

            num = wp.Quantity__c;
            invoiceNum =  wp.InvoiceNo__c;
            freeNum = wp.WarrantyNo__c;

            maxNum = wp.PartsLendingDetails__r.LendingMargin__c;

            oldpartsNum = wp.OldPartsNumber__c;
            newpartsNum = wp.NewPartsNumber__c;
            lendingName = wp.PartsLendingDetails__r.PartsLendingApplication__r.Name;



        }

        public ProductBean(PartsLendingDetails__c p ){
            productId = p.Product__c;
            productName = p.Product__r.Name;

            brand = p.Product__r.Brand__c;
            cate0 = p.Product__r.Category0__c;
            nccode = p.Product__r.NCCode__c;
            lendingName = p.PartsLendingApplication__r.Name;
            lendingId = p.Id;
            maxNum = p.LendingMargin__c ;
            brand = p.Product__r.Brand__c;
            nccode = p.Product__r.NCCode__c;
            spec = p.Product__r.Spec__c;
            serialno = p.Product__r.SerialNo__c;
            cate0 = p.Product__r.Category0__c;


        }
        
    }
    
}